// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ws

import (
	"encoding/json"
)

type Payload struct {
	Cmd      string `json:"cmd"`
	Type     int    `json:"type"`
	Content  string `json:"content"`
	Sender   int    `json:"Sender"`
	Receiver int    `json:"Receiver"`
	ChatId   int    `json:"chat_id"`
	ToRole   string `json:"to_role"`
}

type OfflineMessage struct {
	Cmd    string `json:"cmd"`
	Leaver int    `json:"leaver"`
}

var Broadcast = make(chan []byte)
var Talk = make(chan []byte)
var Register = make(chan *Client)
var Unregister = make(chan *Client)
var Clients = make(map[*Client]bool)
var Users = make(map[int]*Client)
var Guests = make(map[int]*Client)

func SendToUser(uid int, message []byte) {
	if client, ok := Users[uid]; ok {
		client.send <- message
	}
}

func SendToGuest(uid int, message []byte) {
	if client, ok := Guests[uid]; ok {
		client.send <- message
	}
}

func SendToRole(uid int, role string, message []byte) {
	if role == "user" {
		SendToUser(uid, message)
	} else {
		SendToGuest(uid, message)
	}
}

func OfflineNotice(uid int) {
	message, _ := json.Marshal(OfflineMessage{
		Cmd:    "offline",
		Leaver: uid,
	})
	//将离线通知发送给所有客服
	for _, client := range Users {
		client.send <- message
	}
}

func IsOnline(uid int, role string) bool {
	if role == "user" {
		_, ok := Users[uid]
		return ok
	}

	if role == "guest" {
		_, ok := Guests[uid]
		return ok
	}

	return false
}

func Run() {
	for {
		select {
		case client := <-Register:
			Clients[client] = true
			if client.role == "user" {
				Users[client.uid] = client
			} else {
				Guests[client.uid] = client
			}
		case client := <-Unregister:
			if client.role == "user" {
				delete(Users, client.uid)
			} else {
				delete(Guests, client.uid)
				//发送离线通知
				go OfflineNotice(client.uid)
			}
			delete(Clients, client)
			close(client.send)
		case message := <-Broadcast:
			for client := range Clients {
				select {
				case client.send <- message:
				default:
					close(client.send)
					delete(Clients, client)
				}
			}
		case message := <-Talk:
			payload := Payload{}
			json.Unmarshal(message, &payload)
			SendToRole(payload.Receiver, payload.ToRole, message)
		}
	}
}
